#pragma once
#include "Utility/Algebra/Point.h"
#include "Utility/Algebra/Matrix.h"

#include "DataStructure/Common/Out.h"
#include "DataStructure/Input/Material/ThermalMaterial.h"
#include "SGFem/Integration/IntegrationFormula/Gauss3D2X2X2P.h"
#include "SGFem/Integration/IntegrationFormula/Gauss2D2X2P.h"
#include "SGFem/Integration/ShapeFunction/Hexa8NodeShpFunc.h"
#include "SGFem/Integration/ShapeFunction/Plane4NodeShpFunc.h"
#include "SGFem/ElementCalculator/Common/ElementCalculatorExport.h"
#include "SGFem/ElementCalculator/Interface/IElementCalculator.h"

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN
class ElementCalculator_DECLSPEC Hexa8ThermalCalculator : public SG::FEMSolver::Element::IElementCalculator
{
public:
    Hexa8ThermalCalculator () = default;
    virtual ~Hexa8ThermalCalculator () = default;
    /// @brief 计算和节点坐标无关的变量
    virtual void Initialize (SG::DataStructure::FEM::ElementTypes type) override;

    /** @brief 计算应变矩阵B
     * 
     * @param [in] iGauss 积分点索引
     * @param [in] coord 单元节点坐标
     * @param [out] B    应变矩阵
     * @param [out] j 积分点雅克比的行列式值
     */ 
    void ComputeStrainMatrix(std::size_t iGauss, const SG::Algebra::Matrix& coord, _OUT SG::Algebra::Matrix& B, _OUT SG::DataStructure::Common::Real& j) const;

    /** @brief 计算表面detJ
     * 
     * @param [in] iGauss 积分点索引
     * @param [in] coord 单元面节点坐标
     * @param [out] j 积分点雅克比的行列式值
     */ 
    void ComputePlanedetJ(std::size_t iGauss, const SG::Algebra::Matrix& coord, _OUT SG::DataStructure::Common::Real& j) const;
    
    
    /** @brief 计算单元刚度矩阵
     * @param [in] coord 单元节点全局坐标
     * @param [in] material 材料属性
     * @param [out] ke 单元刚度矩阵
    */
    void ComputeStiffness
    (
    const SG::Algebra::Matrix& coord,   
    const SG::DataStructure::FEM::ThermalMaterial& material,
    _OUT SG::Algebra::Matrix& ke
    );

    /** @brief 计算单元热容刚度矩阵
     * @param [in] coord 单元节点全局坐标
     * @param [in] material 材料属性
     * @param [out] ke3 单元热容刚度矩阵
    */
    void ComputeCapacityStiffness
    (
    const SG::Algebra::Matrix& coord, 
    const SG::DataStructure::FEM::ThermalMaterial& material,
    _OUT SG::Algebra::Matrix& ke3
    );

    /** @brief 计算单元热源荷载贡献
     * @param [in] coords 单元节点全局坐标
     * @param [in] q 单元节点热源
     * @param [out] p1 单元热源荷载贡献
    */
    void ComputeHeatSourceLoad
    (
    const SG::Algebra::Matrix& coords,
    const std::vector<SG::DataStructure::Common::Real>& q,
    _OUT SG::Algebra::Matrix& p1
    );

    virtual void ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) override;
    virtual void DataRecovery (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int subcaseId, SG::DataStructure::Common::Real time, const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) override;
    virtual void ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) override;
    static ElementCalculatorSP Create () {return std::make_shared<Hexa8ThermalCalculator> ();}
    
private:
    SG::DataStructure::FEM::ElementTypes m_type;           ///< 单元类型
    SG::FEMSolver::Element::Gauss3D2X2X2P       m_integForm; ///< 积分格式
    SG::FEMSolver::Element::Hexa8NodeShpFunc m_shpFunc; ///< 积分点上的形函数
    SG::FEMSolver::Element::Gauss2D2X2P       m_integForm0; ///< 积分格式   //面单元，用于边界条件处理
    SG::FEMSolver::Element::Plane4NodeShpFunc m_shpFunc0; ///< 积分点上的形函数   //面单元，用于边界条件处理
    static std::size_t s_nNode;                          ///< 单元节点数
    static std::size_t s_nDim;                           ///< 空间维数
};

SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE